<template>
  <div class="content-bottom-wrap" ref="bottomWrap">
    <template v-if="showImg">
      <img :src="imgUrl" class="img" />
      <div class="point-wrap" ref="pointWrap">
        <div
          v-for="(item, index) of mdList"
          :key="index"
          class="point-item point-item-rightcontext"
          :class="{ actived: showRightContextActive(index), selected: item.selected }"
          :data-index="index"
          :style="{
            left: item.posi[0] * wrapWidthScale + 'px',
            top: item.posi[1] * wrapHeightScale + 'px'
          }"
        >
          <div class="type-text">
            <div>{{ item.dotNumber }}</div>
            <div>{{ pointTypeText(item.type) }}</div>
          </div>
        </div>
      </div>
      <div class="point-line-wrap" ref="pointLineWrap"></div>
      <div class="rang-point-wrap" ref="rangePoint">
        <div
          class="range-point-item"
          v-for="(item, index) of selectedRangePoint"
          :key="index"
          :style="{
            left: item.posi[0] * wrapWidthScale + 'px',
            top: item.posi[1] * wrapHeightScale + 'px'
          }"
        ></div>
      </div>
    </template>

    <gas-line-map
      v-else
      :chartData="mapData"
      :points="mdList"
      :lines="lxList"
      :centerPoint="rangePoint"
      style="z-index: 7;"
    />
    <Modal
      v-model="visibileSetNature"
      class="modal-p10"
      title="设置点属性"
      @on-ok="handleSetNatureOk"
      @on-cancel="handleSetNatureCancel"
    >
      <Form :model="natureForm" :label-width="100">
        <FormItem label="编号" prop="dotNumber">
          <Input type="number" v-model="natureForm.dotNumber" placeholder="编号" style="width:100%" disabled />
        </FormItem>
        <FormItem label="点类型" prop="dotType">
          <Select v-model="natureForm.dotType">
            <Option value="0">控制点</Option>
            <Option value="1">气源点</Option>
            <Option value="2">调压点</Option>
          </Select>
        </FormItem>
        <FormItem label="色谱仪编号">
          <Input type="number" v-model="natureForm.chromatographNumber" placeholder="流量计编号" style="width:100%" />
        </FormItem>
        <FormItem label="流量计编号">
          <Input type="number" v-model="natureForm.flowmeterNumber" placeholder="流量计编号" style="width:100%" />
        </FormItem>
        <FormItem label="压力计编号">
          <Input type="number" v-model="natureForm.pressureNumber" placeholder="压力计编号" style="width:100%" />
        </FormItem>
        <FormItem label="经度">
          <Input type="number" v-model="natureForm.longitude" placeholder="经度" style="width:100%" />
        </FormItem>
        <FormItem label="纬度">
          <Input type="number" v-model="natureForm.latitude" placeholder="纬度" style="width:100%" />
        </FormItem>
      </Form>
    </Modal>
    <Modal
      v-model="visibileSetGd"
      class="modal-p10"
      title="设置管道"
      @on-ok="handleSetGdOk"
      @on-cancel="handleSetGdCancel"
    >
      <Form :model="gdForm" :label-width="120">
        <FormItem label="管道编号" prop="pipeNumber">
          <Input type="number" v-model="gdForm.pipeNumber" placeholder="编号" style="width:100%" disabled />
        </FormItem>
        <FormItem label="管道类型" prop="texture">
          <Select v-model="gdForm.texture" @on-change="handleChangeGDLX">
            <Option value="1">钢管</Option>
            <Option value="2">聚乙烯管</Option>
          </Select>
        </FormItem>
        <FormItem label="管道内壁粗糙度" prop="roughness">
          <Input v-model="gdForm.roughness" placeholder="粗糙度">
            <span slot="append">毫米</span>
          </Input>
        </FormItem>
        <FormItem label="管网长度" prop="pipeLength">
          <Input v-model="gdForm.pipeLength" placeholder="内径">
            <span slot="append">米</span>
          </Input>
        </FormItem>
        <FormItem label="管道内径" prop="diameter">
          <Input v-model="gdForm.diameter" placeholder="内径">
            <span slot="append">毫米</span>
          </Input>
        </FormItem>
        <FormItem label="管道温度" prop="temperature">
          <Input v-model="gdForm.temperature" placeholder="温度">
            <span slot="append">度</span>
          </Input>
        </FormItem>
        <FormItem label="摩檫力系数公式" prop="lamdaOption">
          <Select v-model="gdForm.lamdaOption" @on-change="handleChangeXSGS">
            <Option value="1">美国天然气协会公式</Option>
            <Option value="2">标准公式</Option>
            <Option value="3">威莫斯公式</Option>
            <Option value="4">潘汉德公式A</Option>
            <Option value="5">潘汉德公式B</Option>
            <Option value="6">阿里特苏里公式</Option>
            <Option value="7">柯列勃洛克公式</Option>
          </Select>
        </FormItem>
        <FormItem label="雷诺数" prop="re">
          <Input v-model="gdForm.re" placeholder="雷诺数" :disabled="hasLLSEdit">
            <span slot="append">无量纲</span>
          </Input>
        </FormItem>
      </Form>
    </Modal>
  </div>
</template>

<script>
import { createNamespacedHelpers } from 'vuex'
import { cloneDeep, each, merge, isEqual, keys, max } from 'lodash'
import GasLineMap from '../Map'
import { eHeatmapOptions } from './chartOptions'
const { mapState, mapActions } = createNamespacedHelpers('modeling')

export default {
  name: 'Modeling',
  components: {
    GasLineMap
  },
  data() {
    return {
      defaultMdProps: {
        dotNumber: undefined,
        flowmeterNumber: undefined,
        pressureNumber: undefined,
        selected: false,
        dotType: undefined,
        longitude: undefined,
        latitude: undefined,
        chromatographNumber: undefined
      },
      defaultLineProps: {
        hasEdit: false,
        pipeNumber: undefined,
        lamdaOption: '1',
        re: 696400,
        temperature: 20,
        roughness: undefined,
        diameter: undefined,
        pipeLength: undefined
      },
      selectedIndex: undefined,
      selectedLxList: [],
      selectedLxIndex: undefined,
      wrapWidthScale: 1,
      wrapHeightScale: 1,
      currentRightcontextIndex: undefined,
      selectedRangePoint: [],
      visibileSetNature: false,
      natureForm: {
        dotType: undefined,
        dotNumber: undefined,
        flowmeterNumber: undefined,
        pressureNumber: undefined,
        longitude: undefined,
        latitude: undefined,
        chromatographNumber: undefined
      },
      showLxContextMenu: false,
      visibileSetGd: false,
      gdForm: {
        pipeNumber: undefined,
        lamdaOption: '1',
        re: 696400,
        temperature: 20,
        roughness: undefined,
        diameter: undefined,
        pipeLength: undefined
      },
      currentPointPosi: null,
      movePointIndex: undefined,
      mdListBak: null,
      lxListBak: null,
      hasLLSEdit: true
    }
  },
  computed: {
    ...mapState([
      'imgUrl',
      'toolType',
      'mdList',
      'lxList',
      'rangePoint',
      'okRangePoint',
      'showRangePoint',
      'hasLxEdit',
      'hasLx',
      'hasMd',
      'hasEdited'
    ]),
    showImg() {
      return !!this.imgUrl && this.hasEdited
    },
    mapData() {
      return merge({}, eHeatmapOptions, {
        bmap: {
          center: this.$store.getters.mapCenter,
          mapStyle: {
            styleJson: [
              {
                featureType: 'poi',
                elementType: 'labels.text.fill',
                stylers: {
                  color: 'transparent',
                  visibility: 'off'
                }
              },
              {
                featureType: 'poi',
                elementType: 'labels.text.fill',
                stylers: {
                  color: 'transparent',
                  visibility: 'off'
                }
              }
            ]
          }
        },
        series: [
          {
            data: []
          }
        ]
      })
    }
  },
  watch: {
    toolType: {
      handler(val, oldVal) {
        switch (val) {
          case 'md':
            this.initMd()
            break
          case 'lx':
            this.initLx()
            break
          case 'fwd':
            this.initFwd()
            break
          case 'lxwt':
            this.initLxwt()
            break
          case 'szd':
            this.initSzd()
            break
          case 'szgd':
            this.initSzgd()
            break
          default:
            this.selectedIndex = undefined
            this.selectedLxIndex = undefined
            this.currentRightcontextIndex = undefined
            this.removeEvent()
            this.clearSelected()
        }
      }
    },
    lxList() {
      this.eachLx()
    },
    okRangePoint() {
      if (this.okRangePoint) {
        this.changeRangePoint(this.selectedRangePoint)
      }
      this.$nextTick(() => {
        this.selectedRangePoint = []
      })
    },
    showRangePoint() {
      this.selectedRangePoint = []
    },
    hasLx() {
      if (!this.hasLx) {
        this.selectedLxIndex = undefined
        this.eachLx()
      }
    },
    hasMd(val, oldVal) {
      if (!val && oldVal) {
        const oldList = cloneDeep(this.mdList)
        each(oldList, item => {
          item.selected = false
        })

        this.changeMdList(oldList)
      }
    },
    hasLxEdit() {
      if (!this.hasLxEdit) {
        this.changeLxList(this.lxListBak)
        this.changeMdList(this.mdListBak)

        this.$nextTick(() => {
          this.lxListBak = []
          this.mdListBak = []
        })
      }
    }
  },
  beforeDestroy() {
    this.removeEvent()
    window.removeEventListener('resize', this.widowResize)
  },
  mounted() {
    window.addEventListener('resize', this.widowResize)
    this.widowResize()
  },
  methods: {
    ...mapActions(['changeMdList', 'changeLxList', 'changeRangePoint']),
    initMd() {
      setTimeout(() => {
        document.addEventListener('click', this.handleMd)
        document.addEventListener('keyup', this.documentEventKey)
      })
    },
    initLx() {
      setTimeout(() => {
        document.addEventListener('keyup', this.documentEventKey)
        document.addEventListener('click', this.handlePointLxClick)
        this.$refs['pointWrap'] && this.$refs['pointWrap'].addEventListener('click', this.handlePointClick)
      })
    },
    initFwd() {
      document.addEventListener('keyup', this.documentEventKey)
      this.$refs['pointWrap'] && this.$refs['pointWrap'].addEventListener('click', this.handleRangePoint)
    },
    initLxwt() {
      this.lxListBak = cloneDeep(this.lxList)
      this.mdListBak = cloneDeep(this.mdList)
      document.addEventListener('mousedown', this.handlePointMouseDown)
    },
    initSzd() {
      this.$refs['pointWrap'] && this.$refs['pointWrap'].addEventListener('click', this.handlePointClickMenu)
    },
    initSzgd() {
      this.$refs['pointLineWrap'] && this.$refs['pointLineWrap'].addEventListener('click', this.handleLxClickMenu)
    },
    pointTypeText(type) {
      let text = ''
      switch (Number(type)) {
        case 1:
          text = '气'
          break
        case 2:
          text = '调'
          break
        default:
          break
      }

      return text
    },
    widowResize() {
      // this.wrapWidthScale = this.$refs['pointWrap'].offsetWidth / 1257
      // this.wrapHeightScale = this.$refs['pointWrap'].offsetHeight / 781
      this.eachLx()
    },
    removeEvent() {
      document.removeEventListener('click', this.handleMd)
      document.removeEventListener('keyup', this.documentEventKey)
      document.removeEventListener('click', this.handlePointLxClick)
      document.removeEventListener('mousedown', this.handlePointMouseDown)
      this.$refs['pointWrap'] && this.$refs['pointWrap'].removeEventListener('click', this.handlePointClick)
      this.$refs['pointWrap'] && this.$refs['pointWrap'].removeEventListener('click', this.handlePointClickMenu)
      this.$refs['pointWrap'] && this.$refs['pointWrap'].removeEventListener('click', this.handleRangePoint)
      this.$refs['pointLineWrap'] && this.$refs['pointLineWrap'].removeEventListener('click', this.handleLxClickMenu)
    },
    showActive(index) {
      return Number(index) === Number(this.selectedIndex)
    },
    showRightContextActive(index) {
      return Number(index) === Number(this.currentRightcontextIndex)
    },
    getMaxIndex() {
      const indexList = []
      each(this.mdList, item => {
        indexList.push(item.dotNumber)
      })
      return max(indexList) || 0
    },
    handleMd(e) {
      e.stopPropagation()
      e.preventDefault()
      if (this.currentRightcontextIndex != null && !this.visibileSetNature) {
        this.currentRightcontextIndex = undefined
      } else {
        const hasIn = this.$refs['bottomWrap'] && this.$refs['bottomWrap'].contains(e.target)
        if (hasIn) {
          const dataIndex = e.target.getAttribute('data-index')
          const oldData = cloneDeep(this.mdList)
          if (dataIndex == null) {
            const { offsetX, offsetY } = e
            oldData.push({
              ...this.defaultMdProps,
              posi: [offsetX, offsetY],
              dotNumber: this.getMaxIndex() + 1
            })
          } else {
            this.selectedIndex = dataIndex
            each(oldData, (item, index) => {
              if (index === Number(dataIndex)) {
                item.selected = true
              } else {
                item.selected = false
              }
            })
          }
          this.changeMdList(oldData)
        }
      }
    },
    documentEventKey(e) {
      e.preventDefault()
      e.stopPropagation()
      const { keyCode } = e
      switch (Number(keyCode)) {
        case 46: // 按删除按钮
          if (this.selectedIndex != null) {
            const oldArr = cloneDeep(this.mdList)
            oldArr.splice(this.selectedIndex, 1)
            this.changeMdList(oldArr)
            this.selectedIndex = undefined
          }
          if (this.toolType === 'lx' && this.selectedLxIndex != null) {
            const oldList = cloneDeep(this.lxList)
            oldList.splice(this.selectedLxIndex, 1)
            this.selectedLxIndex = undefined
            this.$nextTick(() => {
              this.changeLxList(oldList)
            })
          }
          break
        case 13: // 回车
          if (this.toolType === 'lx') {
            this.modifyLxList()
          }
          break
        case 8:
          if (this.toolType === 'lx') {
            if (this.selectedLxList.length > 0) {
              const idx = this.selectedLxList.pop()
              this.mdList[idx].selected = false
            }
          }
          if (this.toolType === 'fwd') {
            this.selectedRangePoint.pop()
          }
          break
        default:
          break
      }
    },
    handlePointClick(e) {
      const target = e.target
      const dataIndex = target.getAttribute('data-index')
      this.currentRightcontextIndex = undefined
      if (dataIndex != null && !this.selectedLxList.includes(dataIndex)) {
        this.selectedLxList.push(dataIndex)
        const oldList = cloneDeep(this.mdList)
        oldList[dataIndex].selected = true
        this.changeMdList(oldList)
      } else {
        this.lxContextmenuCancel()
      }
    },
    modifyLxList() {
      const list = []
      each(this.selectedLxList, item => {
        const cData = this.mdList[item]
        if (cData) {
          list.push(cData)
        }
      })
      const lxArr = []
      for (let i = 1; i < list.length; i++) {
        lxArr.push({
          ...this.defaultLineProps,
          linePoint: [list[i - 1].posi, list[i].posi],
          startDotNumber: list[i - 1].dotNumber,
          endDotNumber: list[i].dotNumber,
          pipeNumber: i,
          mapPosi: [
            [list[i - 1].longitude, list[i - 1].latitude],
            [list[i].longitude, list[i].latitude]
          ]
        })
      }
      this.changeLxList([...this.lxList, ...lxArr])
      this.clearSelected()
    },
    clearSelected() {
      each(this.selectedLxList, item => {
        this.mdList[item].selected = false
      })
      this.selectedLxList = []
    },
    eachLx() {
      this.clearLx()
      this.$nextTick(() => {
        each(this.lxList, (item, index) => {
          this.drawLine(item, index)
        })
      })
    },
    createLineIndex(idx) {
      const tipEl = document.createElement('div')
      tipEl.style.position = 'absolute'
      tipEl.style.left = '50%'
      tipEl.style.color = '#d12159'
      tipEl.innerHTML = idx
      return tipEl
    },
    drawLine(obj, idx) {
      const { linePoint, hasEdit, pipeNumber } = obj
      if (linePoint.length !== 2) return
      const [startPoint, endPoint] = linePoint
      const xPos = endPoint[0] - startPoint[0]
      const yPos = endPoint[1] - startPoint[1]
      const xLen = Math.abs(xPos) * this.wrapWidthScale
      const yLen = Math.abs(yPos) * this.wrapHeightScale
      const deg = (360 * Math.atan(yLen / xLen)) / (2 * Math.PI)
      let cDeg = deg // 默认4象限
      if (xPos < 0 && yPos < 0) {
        // 2象限位置
        cDeg = 180 + deg
      } else if (xPos > 0 && yPos < 0) {
        // 1象限位置
        cDeg = 360 - deg
      } else if (xPos < 0 && yPos > 0) {
        // 3象限位置
        cDeg = 180 - deg
      }
      const leng = yLen / Math.sin((deg * Math.PI) / 180)
      const divEl = document.createElement('div')
      divEl.style.position = 'absolute'
      divEl.style.left = startPoint[0] * this.wrapWidthScale + 'px'
      divEl.style.top = startPoint[1] * this.wrapHeightScale + 'px'
      divEl.style.width = leng + 'px'
      divEl.style.borderTop = '3px solid #d12159'
      divEl.style.transformOrigin = 'left center'
      divEl.style.transform = 'rotate(' + cDeg + 'deg)'
      divEl.style.zIndex = 6
      divEl.style.cursor = 'pointer'
      divEl.setAttribute('data-index', idx)
      if (hasEdit) {
        divEl.style.borderColor = '#33ff00'
      }
      if (Number(idx) === this.selectedLxIndex) {
        divEl.style.borderColor = '#0035f9'
      }
      const tipEl = this.createLineIndex(pipeNumber)
      divEl.appendChild(tipEl)
      this.$refs['pointLineWrap'].appendChild(divEl)
    },
    clearLx() {
      this.$refs['pointLineWrap'] && (this.$refs['pointLineWrap'].innerHTML = '')
    },
    handlePointLxClick(e) {
      e.stopPropagation()
      e.preventDefault()
      const hasIn = this.$refs['pointLineWrap'] && this.$refs['pointLineWrap'].contains(e.target)
      const dataIndex = e.target.getAttribute('data-index')
      if (hasIn && dataIndex != null) {
        this.selectedLxIndex = Number(dataIndex)
        this.eachLx()
      }
    },
    handlePointClickMenu(e) {
      e.stopPropagation()
      e.preventDefault()
      const dataIndex = e.target.getAttribute('data-index')
      if (dataIndex != null) {
        this.currentRightcontextIndex = Number(dataIndex)
        this.natureForm = {
          ...this.mdList[dataIndex],
          dotNumber: Number(dataIndex) + 1
        }
        this.visibileSetNature = true
      } else {
        this.currentRightcontextIndex = undefined
      }
    },
    handleRangePoint(e) {
      e.stopPropagation()
      e.preventDefault()
      const hasIn = this.$refs['pointWrap'] && this.$refs['pointWrap'].contains(e.target)
      const dataIndex = e.target.getAttribute('data-index')
      if (hasIn && dataIndex != null) {
        if (this.selectedRangePoint.length >= 2) {
          this.selectedRangePoint.pop()
        }
        this.selectedRangePoint.push(this.mdList[dataIndex])
      }
    },
    handleSetNatureOk() {
      const oldList = cloneDeep(this.mdList)
      oldList[this.currentRightcontextIndex] = {
        ...oldList[this.currentRightcontextIndex],
        ...this.natureForm
      }
      this.changeMdList(oldList)
      this.handleSetNatureCancel()
    },
    handleSetNatureCancel() {
      this.visibileSetNature = false
      this.natureForm = cloneDeep(this.defaultMdProps)
      this.$nextTick(() => {
        this.currentRightcontextIndex = undefined
      })
    },
    handleLxClickMenu(e) {
      e.stopPropagation()
      e.preventDefault()
      const dataIndex = e.target.getAttribute('data-index')
      if (dataIndex != null) {
        this.selectedLxIndex = Number(dataIndex)
        this.gdForm = {
          ...this.lxList[dataIndex],
          pipeNumber: Number(dataIndex) + 1
        }
        this.visibileSetGd = true
      }
    },
    lxContextmenuCancel() {
      this.selectedLxIndex = undefined
      this.showLxContextMenu = false
    },
    handleSetGdOk() {
      const keyList = keys(this.gdForm)
      let flag = true
      for (let i = 0; i < keyList.length; i++) {
        if (this.gdForm[keyList[i]] == null) {
          flag = false
          break
        }
      }
      const oldList = cloneDeep(this.lxList)
      oldList[this.selectedLxIndex] = {
        ...oldList[this.selectedLxIndex],
        ...this.gdForm,
        hasEdit: flag
      }
      this.changeLxList(oldList)
      this.handleSetGdCancel()
    },
    handleSetGdCancel() {
      this.visibileSetGd = false
      this.gdForm = cloneDeep(this.defaultLineProps)
      this.lxContextmenuCancel()
    },
    lxListWt(point) {
      const oldList = cloneDeep(this.lxList)
      each(oldList, item => {
        const { linePoint } = item
        each(linePoint, (p, index) => {
          if (isEqual(p, this.currentPointPosi)) {
            linePoint[index] = point
          }
        })
      })
      this.changeLxList(oldList)
    },
    pointWt(posi) {
      const oldList = cloneDeep(this.mdList)
      oldList[this.movePointIndex].posi = posi
      this.changeMdList(oldList)
    },
    handlePointMouseDown(e) {
      e.stopPropagation()
      e.preventDefault()
      const dataIndex = e.target.getAttribute('data-index')
      if (dataIndex != null) {
        this.movePointIndex = dataIndex
        const { offsetTop, offsetLeft, offsetWidth } = e.target
        const halfW = offsetWidth / 2
        this.currentPointPosi = [offsetLeft + halfW, offsetTop + halfW]
        document.addEventListener('mousemove', this.handlePointMouseMove)
        document.addEventListener('mouseup', this.handlePointMouseUp)
      }
    },
    handlePointMouseMove(e) {
      const dataIndex = e.target.getAttribute('data-index')
      if (dataIndex == null) {
        const { offsetX, offsetY } = e
        this.pointWt([offsetX, offsetY])
      }
    },
    handlePointMouseUp(e) {
      e.stopPropagation()
      e.preventDefault()
      const dataIndex = e.target.getAttribute('data-index')
      if (dataIndex != null) {
        const { offsetTop, offsetLeft, offsetWidth } = e.target
        const halfW = offsetWidth / 2
        this.lxListWt([offsetLeft + halfW, offsetTop + halfW])
        this.$nextTick(() => {
          this.currentPointPosi = null
          this.movePointIndex = undefined
        })
      }
      document.removeEventListener('mousemove', this.handlePointMouseMove)
      document.removeEventListener('mouseup', this.handlePointMouseUp)
    },
    handleChangeXSGS(val) {
      if (val !== '1') {
        this.hasLLSEdit = false
        this.gdForm.re = undefined
      } else {
        this.gdForm.re = 696400
        this.hasLLSEdit = true
      }
    },
    handleChangeGDLX(val) {
      if (val === '1') {
        this.gdForm.roughness = 0.15
      } else if (val === '2') {
        this.gdForm.roughness = 0.01
      } else {
        this.gdForm.roughness = undefined
      }
    }
  }
}
</script>

<style lang="less" scoped>
@import './index.less';
</style>
